package yxxy.c_020;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * reentrantLock：可重入锁
 * reentrantLock用于代替synchronized
 * 本例中由于m1锁定this，只有在m1执行完成后，m2才可执行。
 * 这里主要用于复习synchronized
 * <p>
 * <p>
 * 使用reentrantLock可以完成同样的功能
 * 需求注意的是，必须要必须要必须要手动释放锁(重要的事情说三遍)
 * 使用synchronized锁定的话如果遇到异常，jvm会自动释放锁。但是lock必须手动释放锁，因此经常在finally中进行锁的释放
 * <p>
 * <p>
 * 使用reentrantLock可以进行"尝试锁定"tryLock，这样无法锁定，或者在指定时间内无法锁定，线程可以决定是否继续等待
 * <p>
 * <p>
 * 使用reentrantLock还可以调用lockInterruptibly方法，可以对线程interrupt方法做出响应，
 * 在一个线程等待锁的过程中，可以被打断
 *
 * @create: 2019-08-26 21:32
 **/
public class ReentrantLock4 {

    public static void main(String[] args) {

        Lock lock = new ReentrantLock();

        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("m1方法执行");
                TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("interrupt 线程被打断了");
            } finally {
                lock.unlock();
            }
        }).start();

        /*
        执行线程2时，因为无法获取锁。所以会一直处于等待状态，这里主线程调用纯种2的interrupt()将线程打断，不再继续执行。
        相当这条线程没有了
         */
        Thread t2 = new Thread(() -> {
            try {
//                lock.lock();  //使用这种方法是无法打断等待的
                lock.lockInterruptibly();   //可以对interrupt()方法作出响应
                System.out.println("m2方法执行");
                TimeUnit.SECONDS.sleep(5);
                System.out.println("m2方法执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("interrupted 线程2被打断了");
            } finally {
                if (lock.tryLock()) {
                    lock.unlock();
                }
            }
        });
        t2.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("尝试打断线程2");
        //打断线程2的等待
        t2.interrupt();
    }
}
